package com.agileboot.attendance.domain.supplier;

import com.agileboot.attendance.constants.AttendanceConstants;
import com.agileboot.attendance.domain.personnel.db.AttPersonnelService;
import com.agileboot.attendance.domain.supplier.command.AddSupplierCommand;
import com.agileboot.attendance.domain.supplier.command.UpdateSupplierCommand;
import com.agileboot.attendance.domain.supplier.db.AttSupplierEntity;
import com.agileboot.attendance.domain.supplier.db.AttSupplierService;
import com.agileboot.attendance.domain.supplier.dto.SearchSupplierDTO;
import com.agileboot.attendance.domain.supplier.dto.SupplierDTO;
import com.agileboot.attendance.domain.supplier.dto.SupplierOptionDTO;
import com.agileboot.attendance.domain.supplier.model.SupplierModel;
import com.agileboot.attendance.domain.supplier.model.SupplierModelFactory;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.core.page.PageQuery;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.core.command.BulkOperationCommand;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 供应商应用服务类
 * </p>
 *
 * @author agileboot
 * @since 2023-03-14
 */
@Service
@RequiredArgsConstructor
public class SupplierApplicationService {

    private final AttSupplierService supplierService;
    private final AttPersonnelService personnelService;
    private final SupplierModelFactory supplierModelFactory;

    /**
     * 获取供应商分页列表
     *
     * @param query 查询参数
     * @return 分页结果
     */
    public PageDTO<SupplierDTO> getSupplierList(PageQuery<SearchSupplierDTO> query) {
        Page<AttSupplierEntity> page = supplierService.getSupplierList(query);
        List<SupplierDTO> supplierDTOList = page.getRecords().stream()
            .map(supplier -> {
                SupplierDTO dto = new SupplierDTO(supplier);
                // 查询该供应商下的人员数量
                dto.setPersonnelCount(personnelService.countBySupplierId(supplier.getSupplierId()));
                return dto;
            })
            .collect(Collectors.toList());

        return new PageDTO<>(supplierDTOList, page.getTotal());
    }

    /**
     * 根据ID获取供应商详情
     *
     * @param supplierId 供应商ID
     * @return 供应商详情
     */
    public SupplierDTO getSupplierInfo(Long supplierId) {
        AttSupplierEntity supplier = supplierService.getById(supplierId);
        SupplierDTO dto = new SupplierDTO(supplier);
        // 查询该供应商下的人员数量
        dto.setPersonnelCount(personnelService.countBySupplierId(supplier.getSupplierId()));
        return dto;
    }

    /**
     * 添加供应商
     *
     * @param command 添加命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void addSupplier(AddSupplierCommand command) {
        SupplierModel model = supplierModelFactory.create();
        model.loadAddCommand(command);

        model.checkSupplierCodeIsUnique();
        model.checkSupplierNameIsUnique();

        model.insert();
    }

    /**
     * 更新供应商
     *
     * @param command 更新命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSupplier(UpdateSupplierCommand command) {
        SupplierModel model = supplierModelFactory.loadById(command.getSupplierId());
        model.loadUpdateCommand(command);

        model.checkSupplierCodeIsUnique();
        model.checkSupplierNameIsUnique();

        model.updateById();
    }

    /**
     * 删除供应商
     *
     * @param command 批量操作命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteSupplier(BulkOperationCommand<Long> command) {
        for (Long id : command.getItems()) {
            SupplierModel model = supplierModelFactory.loadById(id);
            
            // 检查是否可以删除（是否有关联的人员）
            model.checkCanBeDelete();
            
            model.deleteById();
        }
    }
    
    /**
     * 导出供应商数据
     *
     * @param searchSupplierDTO 查询参数
     * @param response 响应对象
     */
    public void exportSupplier(SearchSupplierDTO searchSupplierDTO, HttpServletResponse response) {
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("供应商列表", StandardCharsets.UTF_8.toString());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            
            // 查询所有满足条件的供应商数据
            PageQuery<SearchSupplierDTO> query = new PageQuery<>();
            query.setParam(searchSupplierDTO);
            query.setPageSize(Integer.MAX_VALUE); // 不分页，导出全部
            query.setPageNum(1);
            
            System.out.println("导出供应商数据，查询参数: " + searchSupplierDTO);
            
            Page<AttSupplierEntity> page = supplierService.getSupplierList(query);
            System.out.println("查询到的供应商数量: " + page.getRecords().size());
            
            List<SupplierDTO> supplierDTOList = page.getRecords().stream()
                .map(supplier -> {
                    SupplierDTO dto = new SupplierDTO(supplier);
                    // 查询该供应商下的人员数量
                    dto.setPersonnelCount(personnelService.countBySupplierId(supplier.getSupplierId()));
                    return dto;
                })
                .collect(Collectors.toList());
            
            System.out.println("转换后的DTO数量: " + supplierDTOList.size());
            
            // 导出Excel
            EasyExcel.write(response.getOutputStream(), SupplierDTO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("供应商列表")
                .doWrite(supplierDTOList);
                
            System.out.println("Excel导出完成");
        } catch (IOException e) {
            System.err.println("导出失败，异常信息: " + e.getMessage());
            e.printStackTrace();
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "导出失败");
        }
    }
    
    /**
     * 导入供应商数据
     *
     * @param file Excel文件
     */
    @Transactional(rollbackFor = Exception.class)
    public void importSupplier(MultipartFile file) {
        if (file.isEmpty()) {
            throw new ApiException(ErrorCode.Business.UPLOAD_FILE_IS_EMPTY);
        }
        
        try {
            // 读取Excel文件内容
            List<AddSupplierCommand> commands = EasyExcel.read(file.getInputStream())
                .head(AddSupplierCommand.class)
                .sheet()
                .doReadSync();
            
            // 批量添加供应商
            for (AddSupplierCommand command : commands) {
                addSupplier(command);
            }
        } catch (IOException e) {
            throw new ApiException(ErrorCode.Business.UPLOAD_IMPORT_EXCEL_FAILED, e.getMessage());
        }
    }
    
    /**
     * 下载导入模板
     *
     * @param response 响应对象
     */
    public void downloadImportTemplate(HttpServletResponse response) {
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("供应商导入模板", StandardCharsets.UTF_8.toString());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            
            // 创建模板数据
            List<AddSupplierCommand> templateList = new ArrayList<>();
            AddSupplierCommand template = new AddSupplierCommand();
            template.setSupplierName("上海科技信息有限公司");
            template.setSupplierCode("SUP003");
            template.setContactName("李四");
            template.setContactPhone("13800138001");
            template.setContactEmail("lisi@example.com");
            template.setAddress("上海市浦东新区张江高科技园区");
            template.setStatus(AttendanceConstants.SupplierStatus.NORMAL);
            templateList.add(template);
            
            // 导出Excel模板
            EasyExcel.write(response.getOutputStream(), AddSupplierCommand.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("供应商数据")
                .doWrite(templateList);
        } catch (IOException e) {
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "模板下载失败");
        }
    }
    
    /**
     * 获取供应商下拉选项列表
     *
     * @return 供应商选项列表
     */
    public List<SupplierOptionDTO> getSupplierOptions() {
        return supplierService.lambdaQuery()
            .eq(AttSupplierEntity::getStatus, AttendanceConstants.SupplierStatus.NORMAL)
            .list()
            .stream()
            .map(supplier -> new SupplierOptionDTO(
                supplier.getSupplierId(),
                supplier.getSupplierName(),
                supplier.getSupplierCode(),
                supplier.getStatus()
            ))
            .collect(Collectors.toList());
    }

    /**
     * 根据项目ID获取关联的供应商列表
     *
     * @param projectId 项目ID
     * @param pageQuery 分页参数
     * @return 供应商分页列表
     */
    public PageDTO<SupplierDTO> getSupplierListByProjectId(Long projectId, PageQuery pageQuery) {
        if (projectId == null) {
            throw new ApiException(ErrorCode.Business.PROJECT_OBJECT_NOT_FOUND, "未指定项目ID");
        }
        
        // 从Order表中查询projectId关联的所有supplierId
        List<Long> supplierIds = supplierService.getBaseMapper().getSupplierIdsByProjectId(projectId);
        
        if (supplierIds.isEmpty()) {
            List<SupplierDTO> emptyList = new ArrayList<>();
            return new PageDTO<>(emptyList, 0L);
        }
        
        // 创建查询条件，根据supplierIds列表查询供应商
        Page<AttSupplierEntity> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        page = supplierService.lambdaQuery()
            .in(AttSupplierEntity::getSupplierId, supplierIds)
            .orderByDesc(AttSupplierEntity::getCreateTime)
            .page(page);
        
        // 转换为DTO
        List<SupplierDTO> supplierDTOList = page.getRecords().stream()
            .map(supplier -> {
                SupplierDTO dto = new SupplierDTO(supplier);
                // 查询该供应商下的人员数量
                dto.setPersonnelCount(personnelService.countBySupplierId(supplier.getSupplierId()));
                return dto;
            })
            .collect(Collectors.toList());
        
        return new PageDTO<>(supplierDTOList, page.getTotal());
    }
} 